/**
 * @file opencv_wrapper.cpp
 * @brief OpenCV功能的C接口实现
 * @version 2.0
 * @date 2023-03-27
 * 
 * 这个文件提供了OpenCV C++功能的C接口封装
 * 使得C代码可以间接使用OpenCV库
 * 增加了对双800W摄像头的立体视觉处理功能
 */

#include <opencv2/opencv.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "image_process.h"

// C接口的OpenCV功能实现

extern "C" {

// 调整图像大小
bool opencv_resize_image(const unsigned char* src_data, int src_width, int src_height, int src_channels,
                       unsigned char* dst_data, int dst_width, int dst_height) {
    try {
        cv::Mat src_mat(src_height, src_width, CV_8UC(src_channels), (void*)src_data);
        cv::Mat dst_mat(dst_height, dst_width, CV_8UC(src_channels), dst_data);
        
        cv::resize(src_mat, dst_mat, cv::Size(dst_width, dst_height), 0, 0, cv::INTER_LINEAR);
        return true;
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 灰度图转换
void opencv_grayscale_image(const unsigned char* src_data, int src_width, int src_height, int src_channels,
                          unsigned char* dst_data) {
    try {
        cv::Mat src_mat(src_height, src_width, CV_8UC(src_channels), (void*)src_data);
        cv::Mat dst_mat(src_height, src_width, CV_8UC1, dst_data);
        
        if (src_channels == 1) {
            // 已经是灰度图
            src_mat.copyTo(dst_mat);
        } else {
            // 转换为灰度图
            cv::cvtColor(src_mat, dst_mat, cv::COLOR_BGR2GRAY);
        }
    } catch (const cv::Exception& e) {
        // 出错时，简单地清空目标图
        memset(dst_data, 0, src_width * src_height);
    }
}

// 图像模糊处理
void opencv_blur_image(const unsigned char* src_data, int src_width, int src_height, int src_channels,
                     unsigned char* dst_data, int kernel_size) {
    try {
        cv::Mat src_mat(src_height, src_width, CV_8UC(src_channels), (void*)src_data);
        cv::Mat dst_mat(src_height, src_width, CV_8UC(src_channels), dst_data);
        
        cv::GaussianBlur(src_mat, dst_mat, cv::Size(kernel_size, kernel_size), 0);
    } catch (const cv::Exception& e) {
        // 出错时，复制源图像
        memcpy(dst_data, src_data, src_width * src_height * src_channels);
    }
}

// 新增：保存图像到文件
/**
 * @brief 保存图像到文件（支持JPG和PNG格式）
 * 
 * @param image_data 图像数据
 * @param width 图像宽度
 * @param height 图像高度
 * @param channels 颜色通道数(1=灰度，3=RGB)
 * @param filename 文件名(包含路径)
 * @param quality 图像质量(0-100，仅对JPEG有效)
 * @return true 保存成功
 * @return false 保存失败
 */
bool opencv_save_image(const unsigned char* image_data, int width, int height, int channels,
                      const char* filename, int quality) {
    try {
        if (!image_data || width <= 0 || height <= 0 || (channels != 1 && channels != 3 && channels != 4) || !filename) {
            return false;
        }
        
        // 创建OpenCV Mat对象
        cv::Mat img(height, width, CV_8UC(channels), (void*)image_data);
        
        // 如果是BGR格式转为RGB格式（OpenCV默认BGR，标准图像文件格式为RGB）
        cv::Mat save_img;
        if (channels == 3 || channels == 4) {
            cv::cvtColor(img, save_img, cv::COLOR_BGR2RGB);
        } else {
            save_img = img;
        }
        
        // 根据文件扩展名确定图像格式并保存
        std::vector<int> compression_params;
        std::string fname(filename);
        std::string ext = fname.substr(fname.find_last_of(".") + 1);
        
        if (ext == "jpg" || ext == "jpeg" || ext == "JPG" || ext == "JPEG") {
            compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
            compression_params.push_back(quality);
        } else if (ext == "png" || ext == "PNG") {
            compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
            compression_params.push_back(quality / 10); // PNG压缩范围是0-9
        }
        
        return cv::imwrite(filename, save_img, compression_params);
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 边缘检测
bool opencv_detect_edges(const unsigned char* src_data, int src_width, int src_height,
                       unsigned char* dst_data, int threshold_value) {
    try {
        cv::Mat src_mat(src_height, src_width, CV_8UC1, (void*)src_data);
        cv::Mat dst_mat(src_height, src_width, CV_8UC1, dst_data);
        
        // 使用Canny边缘检测
        cv::Canny(src_mat, dst_mat, threshold_value / 2, threshold_value);
        
        // 膨胀边缘以便更好地连接
        cv::dilate(dst_mat, dst_mat, cv::Mat(), cv::Point(-1, -1), 1);
        
        return true;
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 查找轮廓
bool opencv_find_contours(const unsigned char* src_data, int src_width, int src_height,
                        ImageContour* contours, int max_contours, int* num_contours) {
    try {
        cv::Mat src_mat(src_height, src_width, CV_8UC1, (void*)src_data);
        std::vector<std::vector<cv::Point>> cv_contours;
        std::vector<cv::Vec4i> hierarchy;
        
        // 查找轮廓
        cv::findContours(src_mat.clone(), cv_contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
        
        // 限制轮廓数量
        int n = (int)cv_contours.size() < max_contours ? (int)cv_contours.size() : max_contours;
        *num_contours = n;
        
        // 填充结果
        for (int i = 0; i < n; i++) {
            // 计算轮廓面积
            contours[i].area = cv::contourArea(cv_contours[i]);
            
            // 计算边界矩形
            cv::Rect rect = cv::boundingRect(cv_contours[i]);
            contours[i].x = rect.x;
            contours[i].y = rect.y;
            contours[i].width = rect.width;
            contours[i].height = rect.height;
        }
        
        return true;
    } catch (const cv::Exception& e) {
        *num_contours = 0;
        return false;
    }
}

// 绘制轮廓
bool opencv_draw_contours(unsigned char* image_data, int width, int height, int channels,
                        const ImageContour* contours, int num_contours, 
                        unsigned char b, unsigned char g, unsigned char r, unsigned char a) {
    try {
        cv::Mat img(height, width, CV_8UC(channels), image_data);
        
        for (int i = 0; i < num_contours; i++) {
            cv::Rect rect(contours[i].x, contours[i].y, contours[i].width, contours[i].height);
            cv::rectangle(img, rect, cv::Scalar(b, g, r), 2);
        }
        
        return true;
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 新增：从文件加载图像
bool opencv_load_image(const char* filename, unsigned char** data, int* width, int* height, int* channels) {
    try {
        // 使用OpenCV加载图像
        cv::Mat img = cv::imread(filename);
        if (img.empty()) {
            return false;
        }
        
        // 设置输出参数
        *width = img.cols;
        *height = img.rows;
        *channels = img.channels();
        
        // 分配内存并复制图像数据
        size_t data_size = img.cols * img.rows * img.channels();
        *data = (unsigned char*)malloc(data_size);
        if (*data == NULL) {
            return false;
        }
        
        memcpy(*data, img.data, data_size);
        return true;
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 新增：立体匹配处理 - 用于双800W摄像头的立体视觉
bool opencv_stereo_matching(const unsigned char* left_data, const unsigned char* right_data,
                          int width, int height, int channels,
                          float* disparity_data, float* depth_data,
                          float baseline, float focal_length) {
    try {
        // 转换输入图像为cv::Mat
        cv::Mat left_mat(height, width, CV_8UC(channels), (void*)left_data);
        cv::Mat right_mat(height, width, CV_8UC(channels), (void*)right_data);
        
        // 转换为灰度图
        cv::Mat left_gray, right_gray;
        if (channels == 1) {
            left_gray = left_mat;
            right_gray = right_mat;
        } else {
            cv::cvtColor(left_mat, left_gray, cv::COLOR_BGR2GRAY);
            cv::cvtColor(right_mat, right_gray, cv::COLOR_BGR2GRAY);
        }
        
        // 创建SGBM立体匹配器
        int minDisparity = 0;
        int numDisparities = 64;  // 必须是16的倍数
        int blockSize = 9;
        
        cv::Ptr<cv::StereoSGBM> sgbm = cv::StereoSGBM::create(
            minDisparity, numDisparities, blockSize,
            8 * blockSize * blockSize, 32 * blockSize * blockSize,
            1, 0, 5, 100, 32, cv::StereoSGBM::MODE_SGBM);
        
        // 计算视差图
        cv::Mat disparity;
        sgbm->compute(left_gray, right_gray, disparity);
        
        // 转换为浮点视差图
        cv::Mat disparity_float;
        disparity.convertTo(disparity_float, CV_32F, 1.0/16.0);
        
        // 计算深度图
        cv::Mat depth(disparity_float.size(), CV_32F);
        // 只计算有效视差的深度
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                float disp = disparity_float.at<float>(y, x);
                if (disp > 0) {
                    // 根据视差计算深度：深度 = 基线 * 焦距 / 视差
                    depth.at<float>(y, x) = baseline * focal_length / disp;
                } else {
                    depth.at<float>(y, x) = 0;  // 无效深度
                }
            }
        }
        
        // 复制结果到输出数组
        memcpy(disparity_data, disparity_float.data, width * height * sizeof(float));
        memcpy(depth_data, depth.data, width * height * sizeof(float));
        
        return true;
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 新增：线缆提取和测量 - 专用于覆冰线缆提取
bool opencv_extract_cable(const unsigned char* image_data, int width, int height, int channels,
                        float* cable_diameter, float* ice_thickness,
                        float known_diameter_mm, float pixels_per_mm) {
    try {
        // 将输入数据转换为OpenCV Mat
        cv::Mat img(height, width, CV_8UC(channels), (void*)image_data);
        cv::Mat gray, blur, binary;
        
        // 转换为灰度图
        if (channels == 1) {
            gray = img;
        } else {
            cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
        }
        
        // 高斯模糊减少噪声
        cv::GaussianBlur(gray, blur, cv::Size(5, 5), 0);
        
        // 自适应阈值处理
        cv::adaptiveThreshold(blur, binary, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, 
                             cv::THRESH_BINARY_INV, 11, 2);
        
        // 形态学操作清理图像
        cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
        cv::morphologyEx(binary, binary, cv::MORPH_OPEN, kernel);
        
        // 查找轮廓
        std::vector<std::vector<cv::Point>> contours;
        std::vector<cv::Vec4i> hierarchy;
        cv::findContours(binary, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
        
        // 寻找最可能是线缆的轮廓
        double maxArea = 0;
        int maxIdx = -1;
        
        for (size_t i = 0; i < contours.size(); i++) {
            double area = cv::contourArea(contours[i]);
            if (area > maxArea) {
                // 计算轮廓的最小外接矩形
                cv::RotatedRect rRect = cv::minAreaRect(contours[i]);
                // 获取矩形的短边作为线缆直径
                float width = std::min(rRect.size.width, rRect.size.height);
                // 只考虑合理大小的轮廓
                if (width > 5 && width < 200) {
                    maxArea = area;
                    maxIdx = i;
                }
            }
        }
        
        // 如果找到了合适的轮廓
        if (maxIdx >= 0) {
            // 计算最小外接矩形
            cv::RotatedRect rRect = cv::minAreaRect(contours[maxIdx]);
            
            // 获取矩形的短边作为线缆直径(像素)
            float diameter_px = std::min(rRect.size.width, rRect.size.height);
            
            // 转换为毫米
            float measured_diameter_mm = diameter_px / pixels_per_mm;
            
            // 计算覆冰厚度
            float ice_thickness_mm = (measured_diameter_mm - known_diameter_mm) / 2.0f;
            if (ice_thickness_mm < 0) ice_thickness_mm = 0;
            
            // 输出结果
            *cable_diameter = measured_diameter_mm;
            *ice_thickness = ice_thickness_mm;
            
            return true;
        }
        
        return false;
    } catch (const cv::Exception& e) {
        return false;
    }
}

// 新增：在图像上添加标注信息 - 用于调试模式
bool opencv_annotate_image(unsigned char* image_data, int width, int height, int channels,
                          const char* timestamp,
                          float temperature, float humidity,
                          float wind_speed, float wind_direction,
                          float tension1, float tension2) {
    try {
        // 将输入数据转换为OpenCV Mat
        cv::Mat img(height, width, CV_8UC(channels), image_data);
        
        // 定义文本位置和字体设置
        int font_face = cv::FONT_HERSHEY_SIMPLEX;
        double font_scale = 0.8;
        int thickness = 2;
        int line_spacing = 35;
        cv::Scalar text_color(0, 0, 255); // 红色
        cv::Scalar bg_color(255, 255, 255); // 白色背景
        
        // 创建要显示的文本信息 - 替换中文为英文
        std::vector<std::string> text_lines;
        text_lines.push_back(std::string("Time: ") + timestamp);
        
        char buffer[64];
        sprintf(buffer, "Temp: %.1f°C", temperature);
        text_lines.push_back(buffer);
        
        sprintf(buffer, "Humidity: %.1f%%", humidity);
        text_lines.push_back(buffer);
        
        sprintf(buffer, "Wind Speed: %.1f m/s", wind_speed);
        text_lines.push_back(buffer);
        
        sprintf(buffer, "Wind Direction: %.1f°", wind_direction);
        text_lines.push_back(buffer);
        
        sprintf(buffer, "Tension 1: %.1f N", tension1);
        text_lines.push_back(buffer);
        
        sprintf(buffer, "Tension 2: %.1f N", tension2);
        text_lines.push_back(buffer);
        
        // 绘制半透明背景
        int bg_width = 300; // 增加背景宽度以适应英文文本
        int bg_height = (int)text_lines.size() * line_spacing + 20;
        cv::Rect bg_rect(10, 10, bg_width, bg_height);
        cv::Mat overlay = img(bg_rect).clone();
        cv::rectangle(img, bg_rect, bg_color, -1); // 填充白色背景
        
        // 添加文本
        for (size_t i = 0; i < text_lines.size(); i++) {
            cv::Point text_pos(20, 40 + i * line_spacing);
            cv::putText(img, text_lines[i], text_pos, font_face, font_scale, text_color, thickness);
        }
        
        // 将半透明背景与原图像混合
        cv::addWeighted(img(bg_rect), 0.7, overlay, 0.3, 0, img(bg_rect));
        
        // 添加边框
        cv::rectangle(img, bg_rect, cv::Scalar(0, 0, 0), 2);
        
        return true;
    } catch (const cv::Exception& e) {
        fprintf(stderr, "OpenCV error: %s\n", e.what());
        return false;
    }
}

/**
 * @brief 在图像上添加自定义文本
 * 
 * @param image_data 图像数据
 * @param width 图像宽度
 * @param height 图像高度
 * @param channels 颜色通道数(1=灰度，3=RGB)
 * @param text 要添加的文本
 * @return true 标注成功
 * @return false 标注失败
 */
bool opencv_add_custom_text(unsigned char* image_data, int width, int height, int channels,
                          const char* text) {
    try {
        // 将输入数据转换为OpenCV Mat
        cv::Mat img(height, width, CV_8UC(channels), image_data);
        
        // 定义文本位置和字体设置
        int font_face = cv::FONT_HERSHEY_SIMPLEX;
        double font_scale = 1.0;  // 字体比标准标注稍大
        int thickness = 2;
        cv::Scalar text_color(255, 0, 0);  // 蓝色文本
        cv::Scalar bg_color(255, 255, 255);  // 白色背景
        
        // 测量文本大小，以便创建合适的背景
        cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, nullptr);
        
        // 计算背景矩形
        int padding = 10;  // 文本周围的内边距
        cv::Rect bg_rect(10, height - text_size.height - 2 * padding - 40, 
                        text_size.width + 2 * padding, text_size.height + 2 * padding);
        
        // 绘制背景
        cv::rectangle(img, bg_rect, bg_color, -1);
        
        // 绘制文本
        cv::Point text_pos(bg_rect.x + padding, bg_rect.y + text_size.height + padding / 2);
        cv::putText(img, text, text_pos, font_face, font_scale, text_color, thickness);
        
        return true;
    } catch (const cv::Exception& e) {
        fprintf(stderr, "OpenCV error: %s\n", e.what());
        return false;
    }
}

} // extern "C" 